package com.warom.sdg.util;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * 开放平台API客户端
 * 实现开放平台接口调用，包括签名验证等功能
 */
public class OpenApiClient {
    private static final String TAG = "OpenApiClient";
    
    // JSON媒体类型
    private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    
    // 配置文件名称
    private static final String PREF_NAME = "open_api_config";
    
    // 配置项Key
    private static final String KEY_APP_KEY = "app_key";
    private static final String KEY_APP_SECRET = "app_secret";
    
    // OkHttpClient实例
    private static OkHttpClient client;
    
    // 应用上下文
    private static Context appContext;
    
    // API凭证
    private static String appKey;
    private static String appSecret;
    
    // 初始化OkHttpClient
    static {
        client = new OkHttpClient.Builder()
                .connectTimeout(10, java.util.concurrent.TimeUnit.SECONDS)
                .readTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
                .writeTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
                .build();
    }
    
    /**
     * 初始化客户端
     * @param context 上下文
     * @param apiKey 应用key
     * @param apiSecret 应用密钥
     */
    public static void init(Context context, String apiKey, String apiSecret) {
        if (context != null) {
            appContext = context.getApplicationContext();
            appKey = apiKey;
            appSecret = apiSecret;
            
            // 保存配置到SharedPreferences
            saveConfig();
        }
    }
    
    /**
     * 初始化客户端（从SharedPreferences读取配置）
     * @param context 上下文
     */
    public static void init(Context context) {
        if (context != null) {
            appContext = context.getApplicationContext();
            
            // 从SharedPreferences加载配置
            loadConfig();
        }
    }
    
    /**
     * 保存配置到SharedPreferences
     */
    private static void saveConfig() {
        if (appContext != null && appKey != null && appSecret != null) {
            SharedPreferences preferences = appContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
            preferences.edit()
                    .putString(KEY_APP_KEY, appKey)
                    .putString(KEY_APP_SECRET, appSecret)
                    .apply();
        }
    }
    
    /**
     * 从SharedPreferences加载配置
     */
    private static void loadConfig() {
        if (appContext != null) {
            SharedPreferences preferences = appContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
            appKey = preferences.getString(KEY_APP_KEY, "");
            appSecret = preferences.getString(KEY_APP_SECRET, "");
        }
    }
    
    /**
     * 设置应用Key
     * @param apiKey 应用Key
     */
    public static void setAppKey(String apiKey) {
        appKey = apiKey;
        saveConfig();
    }
    
    /**
     * 设置应用Secret
     * @param apiSecret 应用Secret
     */
    public static void setAppSecret(String apiSecret) {
        appSecret = apiSecret;
        saveConfig();
    }
    
    /**
     * 获取签名字符串
     * @param path 请求路径
     * @return 签名结果
     */
    private static SignatureResult getSignature(String path) {
        try {
            // 获取当前时间戳
            String timestamp = String.valueOf(System.currentTimeMillis());
            
            // 拼接签名原文
            String encryptStr = appKey + path + timestamp;
            
            // 使用HMAC-SHA-256算法生成签名
            String signature = generateHmacSha256Signature(encryptStr, appSecret);
            
            return new SignatureResult(signature, timestamp);
        } catch (Exception e) {
            Log.e(TAG, "生成签名失败: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 使用HMAC-SHA-256算法生成签名
     * @param data 待签名数据
     * @param secret 密钥
     * @return 签名结果（十六进制字符串）
     */
    private static String generateHmacSha256Signature(String data, String secret) 
            throws NoSuchAlgorithmException, InvalidKeyException {
        // 创建HMAC-SHA-256密钥
        SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        
        // 获取Mac实例并初始化
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(secretKeySpec);
        
        // 计算HMAC签名
        byte[] hmacBytes = mac.doFinal(data.getBytes());
        
        // 将字节数组转换为十六进制字符串
        return bytesToHex(hmacBytes);
    }
    
    /**
     * 将字节数组转换为十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            // 0xFF保证无符号转换
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }
    
    /**
     * 解析响应JSON
     * @param responseBody 响应内容
     * @param clazz 返回类型Class
     * @param <T> 返回类型
     * @return 解析结果，失败返回null
     */
    private static <T> T parseResponse(String responseBody, Class<T> clazz) {
        try {
            JsonObject jsonObject = JsonUtil.parseJson(responseBody, JsonObject.class);
            if (jsonObject == null) {
                return null;
            }
            
            int code = jsonObject.get("code").getAsInt();
            String message = jsonObject.get("message").getAsString();
            
            // 检查返回码
            if (code != 0) {
                Log.e(TAG, "API调用失败: " + message);
                return null;
            }
            
            // 解析data部分
            if (!jsonObject.has("data")) {
                return null;
            }
            
            JsonElement dataElement = jsonObject.get("data");
            if (dataElement.isJsonNull()) {
                return null;
            }
            
            return JsonUtil.parseJson(dataElement.toString(), clazz);
            
        } catch (Exception e) {
            Log.e(TAG, "解析响应失败: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 提取API路径
     * @param url 完整URL
     * @return API路径，例如：/openapi/live/stream
     */
    private static String extractPath(String url) {
        // 移除基础URL部分，只保留路径
        if (url.startsWith(Constants.OPEN_API_BASE_URL)) {
            return url.substring(Constants.OPEN_API_BASE_URL.length());
        }
        
        // 尝试解析URL
        try {
            java.net.URL parsedUrl = new java.net.URL(url);
            return parsedUrl.getPath();
        } catch (Exception e) {
            Log.e(TAG, "解析URL路径失败: " + e.getMessage(), e);
            return url; // 返回原始URL作为路径
        }
    }
    
    /**
     * 发送POST请求
     * @param url 请求URL
     * @param jsonData 请求数据JSON字符串
     * @param responseClass 响应类型
     * @param <T> 响应类型泛型
     * @return 响应对象，失败返回null
     */
    public static <T> T post(String url, String jsonData, Class<T> responseClass) {
        try {
            Log.d(TAG, "发送POST请求: " + url);
            Log.d(TAG, "请求数据: " + jsonData);
            
            // 提取API路径
            String path = extractPath(url);
            
            // 生成签名
            SignatureResult signatureResult = getSignature(path);
            if (signatureResult == null) {
                Log.e(TAG, "生成签名失败");
                return null;
            }
            
            // 创建请求体
            RequestBody body = RequestBody.create(JSON, jsonData);
            
            // 构建请求
            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("signature", signatureResult.signature)
                    .addHeader("timestamp", signatureResult.timestamp)
                    .addHeader("appKey", appKey)
                    .build();
            
            // 执行请求
            Response response = client.newCall(request).execute();
            
            // 获取响应内容
            String responseBody = response.body() != null ? response.body().string() : "";
            
            Log.d(TAG, "响应: " + responseBody);
            
            // 检查HTTP状态码
            if (!response.isSuccessful()) {
                Log.e(TAG, "HTTP请求失败: " + response.code() + " - " + response.message());
                return null;
            }
            
            // 解析响应
            return parseResponse(responseBody, responseClass);
            
        } catch (Exception e) {
            Log.e(TAG, "HTTP请求异常: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 获取设备直播地址
     * @param deviceId 设备ID
     * @param channel 通道号
     * @param stream 码流类型（0:高清, 1:标清）
     * @param expireTime 过期时间戳（毫秒）
     * @return 直播地址，失败返回null
     */
    public static String getLiveStream(String deviceId, int channel, int stream, long expireTime) {
        try {
            // 构造请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("deviceId", deviceId);
            params.put("channel", channel);
            params.put("stream", stream);
            params.put("expireTime", String.valueOf(expireTime));
            
            // 转换为JSON
            String jsonData = JsonUtil.toJson(params);
            
            // 发送请求
            LiveStreamResponse response = post(Constants.API_LIVE_STREAM, jsonData, LiveStreamResponse.class);
            
            // 返回直播URL
            return response != null ? response.url : null;
        } catch (Exception e) {
            Log.e(TAG, "获取直播地址失败: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 获取设备直播地址（使用更多参数）
     * @param deviceId 设备ID
     * @param channel 通道号
     * @param stream 码流类型（0:高清, 1:标清）
     * @param expireTime 过期时间戳（毫秒）
     * @param protocol 协议类型
     * @param videoCode 视频编码
     * @return 直播地址，失败返回null
     */
    public static String getLiveStream(String deviceId, int channel, int stream, 
                                      long expireTime, String protocol, String videoCode) {
        try {
            // 构造请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("deviceId", deviceId);
            params.put("channel", channel);
            params.put("stream", stream);
            params.put("expireTime", String.valueOf(expireTime));
            
            // 添加可选参数
            if (protocol != null && !protocol.isEmpty()) {
                params.put("protocol", protocol);
            }
            
            if (videoCode != null && !videoCode.isEmpty()) {
                params.put("videoCode", videoCode);
            }
            
            // 转换为JSON
            String jsonData = JsonUtil.toJson(params);
            
            // 发送请求
            LiveStreamResponse response = post(Constants.API_LIVE_STREAM, jsonData, LiveStreamResponse.class);
            
            // 返回直播URL
            return response != null ? response.url : null;
        } catch (Exception e) {
            Log.e(TAG, "获取直播地址失败: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 设备唤醒
     * @param deviceId 设备ID
     * @param channel 通道号
     * @return 是否成功
     */
    public static boolean wakeupDevice(String deviceId, int channel) {
        try {
            // 构造请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("deviceId", deviceId);
            params.put("channel", channel);
            
            // 转换为JSON
            String jsonData = JsonUtil.toJson(params);
            
            // 发送请求
            WakeupResponse response = post(Constants.API_DEVICE_WAKEUP, jsonData, WakeupResponse.class);
            
            // 返回唤醒结果
            return response != null && response.ret;
        } catch (Exception e) {
            Log.e(TAG, "设备唤醒失败: " + e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 获取设备截图
     * @param deviceId 设备ID
     * @param channel 通道号
     * @return 截图结果，失败返回null
     */
    public static ScreenshotResult getDeviceScreenshot(String deviceId, int channel) {
        return getDeviceScreenshot(deviceId, channel, 1); // 默认不进行害虫识别
    }
    
    /**
     * 获取设备截图
     * @param deviceId 设备ID
     * @param channel 通道号
     * @param rec 是否进行害虫识别（1:不识别, 2:识别）
     * @return 截图结果，失败返回null
     */
    public static ScreenshotResult getDeviceScreenshot(String deviceId, int channel, int rec) {
        try {
            // 构造请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("deviceId", deviceId);
            params.put("channel", channel);
            params.put("rec", rec);
            
            // 转换为JSON
            String jsonData = JsonUtil.toJson(params);
            
            // 发送请求
            return post(Constants.API_DEVICE_SCREENSHOT, jsonData, ScreenshotResult.class);
        } catch (Exception e) {
            Log.e(TAG, "获取设备截图失败: " + e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 签名结果类
     */
    private static class SignatureResult {
        public String signature;
        public String timestamp;
        
        public SignatureResult(String signature, String timestamp) {
            this.signature = signature;
            this.timestamp = timestamp;
        }
    }
    
    /**
     * 获取直播流响应类
     */
    public static class LiveStreamResponse {
        public String url;
    }
    
    /**
     * 设备唤醒响应类
     */
    public static class WakeupResponse {
        public boolean ret;
    }
    
    /**
     * 截图结果类
     */
    public static class ScreenshotResult {
        // 图片URL
        public String image;
        
        // 检测到的害虫列表
        public String[][] pests;
    }
    
    /**
     * 害虫类型枚举
     */
    public static class PestType {
        public static final int RUST_RED_FLAT_GRAIN_BEETLE = 0; // 锈赤扁谷盗
        public static final int ALUMINUM_GRAIN_BEETLE = 1;      // 铝谷盗
        public static final int GRAIN_BORER = 2;                // 谷蠹
        public static final int RICE_WEEVIL = 3;                // 米象
        public static final int RED_FLOUR_BEETLE = 4;           // 赤拟谷盗
        public static final int CORN_WEEVIL = 5;                // 玉米象
        
        // 获取害虫类型名称
        public static String getName(int type) {
            switch (type) {
                case RUST_RED_FLAT_GRAIN_BEETLE:
                    return "锈赤扁谷盗";
                case ALUMINUM_GRAIN_BEETLE:
                    return "铝谷盗";
                case GRAIN_BORER:
                    return "谷蠹";
                case RICE_WEEVIL:
                    return "米象";
                case RED_FLOUR_BEETLE:
                    return "赤拟谷盗";
                case CORN_WEEVIL:
                    return "玉米象";
                default:
                    return "未知类型";
            }
        }
    }
} 